﻿using HPSocketCS;
using System;
using System.Windows.Threading;

namespace NB_Controller_Test
{
    public class UdpServerController : DispatcherObject
    {
        public HPSocketCS.UdpServer udpServer
        {
            get;
            set;
        }

        //public HPSocketCS.UdpCast udpCast;
        //public HPSocketCS.UdpClient udpClient;

        private NetLink netLink = null;

        #region 线程外抛消息代理相关
        private delegate void ConnIDRecvDelegate(IntPtr connId, byte[] bytes);
        private ConnIDRecvDelegate recvDelegate = null;
        private void UDPServerRecvFun(IntPtr connId, byte[] bytes)
        {
            //IP Port解析
            //string strIP = "";
            //UInt16 uiPort = 0;
            //GetIPAndPortByConnId(connId, ref strIP, ref uiPort);

            //string strMsg = GlobalFun.BytesToHexStr(bytes, bytes.Length, "_");

            //打印到后台
            //System.Diagnostics.Debug.WriteLine("Recv " + DateTime.Now.ToString("HH:mm:ss fff [") + strIP + ":" + uiPort.ToString() + "] " + strMsg);

            if (netLink != null)
            {
                netLink.RecvMsg(connId, bytes);
            }                
        }
        #endregion

        public UdpServerController()
        {            
        }

        public void Init(NetLink link, string strIP, ushort usPort)
        {
            InitSocket(strIP, usPort);
            InitDeleFun();

            netLink = link;
        }

        public void Exit()
        {
            if (udpServer != null)
            {
                udpServer.Stop();
            }
        }

        public void GetIPAndPortByConnId(IntPtr connId, ref string strIP, ref UInt16 usPort)
        {
            udpServer.GetRemoteAddress(connId, ref strIP, ref usPort);
        }

        /// <summary>
        /// 向指定客户端（ConnId为标记）发送数据
        /// </summary>
        /// <param name="connId"></param>
        /// <param name="bytes"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        public bool SendData(IntPtr connId, byte[] bytes, int size)
        {
            //二进制数据转换
            //string strInfo;// = Encoding.Default.GetString(bytes);
            //Hex转换
            //strInfo = GlobalFun.BytesToHexStr(bytes, bytes.Length, "_");

            //IP Port解析
            //string strIP = "";
            //UInt16 uiPort = 0;
            //GetIPAndPortByConnId(connId, ref strIP, ref uiPort);

            //打印到后台
            //System.Diagnostics.Debug.WriteLine("Send " + DateTime.Now.ToString("HH:mm:ss fff [") + strIP + ":" + uiPort.ToString() + "] " + strInfo);

            return udpServer.Send(connId, bytes, size);
        }

        #region Private Fun
        private void InitSocket(string strIP, ushort usPort)
        {
            //_udpClient = new HPSocketCS.UdpClient();
            udpServer = new HPSocketCS.UdpServer();
            int nLastError = udpServer.SYSGetLastError();

            // 设置服务器事件
            udpServer.OnPrepareListen += new UdpServerEvent.OnPrepareListenEventHandler(OnPrepareListen_Server);
            udpServer.OnAccept += new UdpServerEvent.OnAcceptEventHandler(OnAccept_Server);
            udpServer.OnSend += new UdpServerEvent.OnSendEventHandler(OnSend_Server);
            // 两个数据到达事件的一种
            //_udpServer.OnPointerDataReceive += new UdpServerEvent.OnPointerDataReceiveEventHandler(OnPointerDataReceive);
            // 两个数据到达事件的一种
            udpServer.OnReceive += new UdpServerEvent.OnReceiveEventHandler(OnReceive_Server);

            udpServer.OnClose += new UdpServerEvent.OnCloseEventHandler(OnClose_Server);
            udpServer.OnShutdown += new UdpServerEvent.OnShutdownEventHandler(OnShutdown_Server);

            udpServer.KeepAliveInterval = 0;
            udpServer.DetectAttempts = 0;

            //_udpClient.Connect(ipAddr.ToString(), (ushort)port);

            //GlobalFun.GetNetCardInfo();
            udpServer.IpAddress = strIP;// tbIP = GlobalFun.GetIPAddress();
            udpServer.Port = usPort;
            //分包大于0x05c0=1472包时将发送失败
            //_udpServer.MaxDatagramSize = 0x05C0;
            bool bOK = udpServer.Start();
            if (!bOK)
            {
                nLastError = udpServer.SYSGetLastError();
                System.Diagnostics.Debug.WriteLine("HPSocket Start Fail");
            }                
        }

        private void InitDeleFun()
        {
            //注册回调函数（通过代理方式）
            recvDelegate = new ConnIDRecvDelegate(UDPServerRecvFun);
        }
        #endregion

        #region HPSocketEvents Server
        HandleResult OnPrepareListen_Server(IntPtr soListen)
        {
            // 监听事件到达了,一般没什么用吧?

            return HandleResult.Ok;
        }

        HandleResult OnAccept_Server(IntPtr connId, IntPtr pClient)
        {
            // 客户进入了

            return HandleResult.Ok;
        }

        HandleResult OnSend_Server(IntPtr connId, byte[] bytes)
        {
            // 服务器发数据了
            return HandleResult.Ok;
        }

        HandleResult OnPointerDataReceive_Server(IntPtr connId, IntPtr pData, int length)
        {
            // 数据到达了
            try
            {
                // 可以通过下面的方法转换到byte[]
                byte[] bytes = new byte[length];
                System.Runtime.InteropServices.Marshal.Copy(pData, bytes, 0, length);

                OnReceive_Server(connId, bytes);

                return HandleResult.Error;
            }
            catch (Exception)
            {
                return HandleResult.Ignore;
            }
        }

        HandleResult OnReceive_Server(IntPtr connId, byte[] bytes)
        {
            // 数据到达了 

            //对界面抛出IP和Port
            this.Dispatcher.BeginInvoke(recvDelegate, connId, bytes);

            return HandleResult.Ok;
        }

        HandleResult OnClose_Server(IntPtr connId, SocketOperation enOperation, int errorCode)
        {
            //if (_udpServer.IsStarted)
            //{
            //    _udpServer.Stop();
            //}
            return HandleResult.Ok;
        }

        HandleResult OnShutdown_Server()
        {
            // 服务关闭了

            return HandleResult.Ok;
        }
        #endregion        
    }
}
